import java.awt.Point;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class TextFieldEventProcessor extends DrawObjectEventProcessor
{
	private void CreateTextFieldArray(Point Pos, String LoadPath, boolean LeftRightOrTopDown, ObjectStorage Objects)
	{
		if (LoadPath != null && (new File(LoadPath)).exists())
		{
			try (BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(LoadPath))))
			{
				int TextFieldPosxNext = Pos.x;
				int TextFieldPosyNext = Pos.y;
				int GridSizex = 50; // TODO: don't hard code
				int GridSizey = 50; // TODO: don't hard code

				while (true)
				{
					String Line = is.readLine();
					if (Line == null)
					{
						is.close();
						break;
					}
					if (Line.length() >= 1)
					{
						Point PlacePosSub = new Point(Pos.x, Pos.y);

						TextField TextFieldAdded = (TextField) Objects.AddObject("TextField", PlacePosSub, null);

						TextFieldAdded.SetText(Line);
						TextFieldAdded.SetPos(new Point(TextFieldPosxNext, TextFieldPosyNext));

						if (LeftRightOrTopDown)
						{
							TextFieldPosxNext = TextFieldPosxNext + (int) (TextFieldAdded.Size.x / GridSizex) * GridSizex + GridSizex;
						}
						else
						{
							TextFieldPosyNext = TextFieldPosyNext + (int) (TextFieldAdded.Size.y / GridSizey) * GridSizey + GridSizey;
						}
					}
				}
			}
			catch (Exception e)
			{
				// ignore, maybe file locked, user sees that nothing is loaded into TextFields
			}
		}
	}

	@Override
	public void TryProcessUserKeyboardAction(MainWindow.GUIElements GUIElements, KeyEventProcessor KeyEventProcessor, MouseEventProcessor MouseEventProcessor, ObjectStorage ObjectStorage, IOProgram IOProgram)
	{
		/*
		// ****************************************************************
		// TextField edit mode (old, Beta 1)
		if (DEFINED(FillTextField))
		{
			if (KeyEventProcessor.IsKeyCodePressed(KeyEvent.VK_ENTER))
			{
				if (((TextField) FillTextField).GetText().length() >= 1)
				{
					TextField TextField = ((TextField) FillTextField);
		
					TextField.SetBeingEdited(false);
		
					FillTextField = UNDEFINED;
		
					if (FillTextField_TextUnchanged != null && FillTextField_TextUnchanged.length() >= 1 && // first two conditions should always be the case
						!(FillTextField_TextUnchanged.equals(DrawObject.TextFieldDefaultText)) && !(FillTextField_TextUnchanged.equals(TextField.GetText()))) // not the same text entered again?
					{
						String TextFieldTextOld = FillTextField_TextUnchanged;
						String TextFieldTextNew = TextField.GetText();
		
						ArrayList<TextField> TextFieldsWithSameText = ObjectStorage.GetTextFieldsByText(TextFieldTextOld);
						if (TextFieldsWithSameText.size() >= 1) // the original one already has the new text, so >= 1 means WERE there two TextFields with this text?
						{
							if (Tools.ShowYesNoDialog(
								GUIElements.GetMainWindow(),
								"There are several TextFields on which the same text change could be applied.\r\n" + "Update all of them?\r\n" + "Notice one activated TextField always activates all others with same text during simulation."
							))
							{
								for (int m = 0; m < TextFieldsWithSameText.size(); m++)
									TextFieldsWithSameText.get(m).SetText(TextFieldTextNew);
							}
						}
					}
		
					GUIElements.GetMainWindow().DoRedraw();
				}
				else
				{
					GUIElements.GetMainWindow().GetTitleBarInfo().AddInfoText("You must enter any text!", true, false, false, false);
				}
			}
			else if (KeyEventProcessor.IsKeyCodePressed(0x08)) // backspace
			{ // buggy, deletes TWO letters at once
			
				((TextField) FillTextField).RemoveOneLetter();
		
				GUIElements.GetMainWindow().DoRedraw();
			}
			else if (KeyEventProcessor.AnyKeyTyped())
			{
				if ((int) (KeyEventProcessor.GetKeyTyped()) >= 32 && // all non-printable control chars are below space (#32), except Del (#127), if user presses Del, Shift, Tab, 65535 is returned (tested)
					(int) (KeyEventProcessor.GetKeyTyped()) != 127 && (int) (KeyEventProcessor.GetKeyTyped()) <= 255) // https://theasciicode.com.ar/
				{
					((TextField) FillTextField).AddText(KeyEventProcessor.GetKeyTyped());
		
					GUIElements.GetMainWindow().DoRedraw();
				}
			}
		}
		*/
		// ****************************************************************

		if (!(KeyboardEventsToBeProcessed(GUIElements)))
			return;

		// ****************************************************************
		// a (create TextField array)
		if (KeyEventProcessor.IsKeyCodePressed(KeyEvent.VK_A) &&
			KeyEventProcessor.IsControlPressed())
		{
			String LoadPath = Tools
				.ShowInputDialog("Path to file containing TextFields' text line-by-line?\r\n(enter just a file name to load from working directory \"" + Settings.GetWorkingDirectory() + "\"\r\nPut in front '-' to line up top down)");

			boolean LeftRightOrTopDown = true;

			if (LoadPath != null)
			{
				if (LoadPath.indexOf('-') == 0)
				{
					LeftRightOrTopDown = false;
					LoadPath = LoadPath.substring(1);
				}
				else
				{
					LeftRightOrTopDown = true;
				}
			}

			if (LoadPath != null && LoadPath.indexOf("/") < 0 && LoadPath.indexOf("\\") < 0)
				LoadPath = (Settings.GetWorkingDirectory() + "/" + LoadPath).replace("//", "/");

			if (LoadPath != null && LoadPath.length() >= 1)
			{
				CreateTextFieldArray(
					DrawObject.AlignOnGrid(DrawObject.UnZoomPoint(MouseEventProcessor.GetMousePosPoint(GUIElements.GetMainWindow()))),
					LoadPath,
					LeftRightOrTopDown,
					ObjectStorage
				);

				GUIElements.GetMainWindow().DoRedraw();
			}
		}
	}

	@Override
	public void TryProcessUserMouseAction(MainWindow.GUIElements GUIElements, KeyEventProcessor KeyEventProcessor, MouseEventProcessor MouseEventProcessor, ObjectStorage ObjectStorage, IOProgram IOProgram)
	{
		if (!(MouseEventsToBeProcessed(GUIElements)))
			return;

		// ****************************************************************
		if (MouseEventProcessor.IsRightButtonClicked())
		{
			if (DEFINED(SingleSelectedObject))
			{
				if (SingleSelectedObject.IsTextField())
				{
					FillTextField = SingleSelectedObject;
					FillTextField_TextUnchanged = ((TextField) FillTextField).GetText();

					// old (Beta 1):
					/*
					((TextField) FillTextField).Clear();
					((TextField) FillTextField).SetBeingEdited(true);
					*/

					// new (Beta 2):
					String TextNew = Tools.ShowInputDialog("Enter new TextField text:", FillTextField_TextUnchanged);

					if (TextNew != null && TextNew.length() >= 1)
					{
						TextField TextField = ((TextField) FillTextField);

						TextField.SetText(TextNew);

						FillTextField = UNDEFINED;

						if (FillTextField_TextUnchanged != null && FillTextField_TextUnchanged.length() >= 1 && // first two conditions should always be the case
							!(FillTextField_TextUnchanged.equals(DrawObject.TextFieldDefaultText)) && !(FillTextField_TextUnchanged.equals(TextField.GetText()))) // not the same text entered again?
						{
							String TextFieldTextOld = FillTextField_TextUnchanged;
							String TextFieldTextNew = TextField.GetText();

							ArrayList<TextField> TextFieldsWithSameText = ObjectStorage.GetTextFieldsByText(TextFieldTextOld);
							if (TextFieldsWithSameText.size() >= 1) // the original one already has the new text, so >= 1 means WERE there two TextFields with this text?
							{
								if (Tools.ShowYesNoDialog(
									GUIElements.GetMainWindow(),
									"There are several TextFields on which the same text change could be applied.\r\n" + "Update all of them?\r\n" + "Notice one activated TextField always activates all others with same text during simulation."
								))
								{
									for (int m = 0; m < TextFieldsWithSameText.size(); m++)
										TextFieldsWithSameText.get(m).SetText(TextFieldTextNew);
								}
							}
						}
					}
					else
					{
						FillTextField = UNDEFINED;
					}

					GUIElements.GetMainWindow().DoRedraw();
					// end of new (Beta 2)
				}
			}
		}

		// ****************************************************************
		if (DEFINED(FillTextField))
		{
			GUIElements.GetMainWindow().GetTitleBarInfo().AddInfoText(FillTextFieldMessage, false, false, true, false);
		}
		else
		{
			GUIElements.GetMainWindow().GetTitleBarInfo().RemoveInfoText(FillTextFieldMessage);
		}

		return;
	}
}
